package com.yeskery.transfer.data;

import lombok.Getter;
import lombok.Setter;

import java.util.stream.LongStream;

/**
 * 页码对象
 * @author shuangjiang.du
 * @date 2018-12-17 11:59
 * @version 1.0
 */
@Getter
@Setter
public class Page {

	/** 默认的分页数 */
	public static final int DEFAULT_PAGINATION_NUM = 200;

	/** 默认的最大线程数 */
	private static final int MAX_THREAD_COUNT = 8;

	/** 总页码 */
	private Long count;

	/** 总页数 */
	private Long pages;

	/** 分页数 */
	private int paginationNum;

	/**
	 * 创建一个页码对象
	 */
	public Page() {
		paginationNum = DEFAULT_PAGINATION_NUM;
	}

	/**
	 * 创建一个页码对象
	 * @param count 总条数
	 * @param pages 总页数
	 */
	public Page(Long count, Long pages) {
		this.count = count;
		this.pages = pages;
		paginationNum = DEFAULT_PAGINATION_NUM;
	}

	/**
	 * 创建一个页码对象
	 * @param count 总条数
	 * @param pages 总页数
	 * @param paginationNum 每页的间隔数
	 */
	public Page(Long count, Long pages, int paginationNum) {
		this.count = count;
		this.pages = pages;
		this.paginationNum = paginationNum;
	}

	/**
	 * 根据线程数获取每条线程应该执行的页码数
	 * @param threadCount 线程数
	 * @return 每条线程应该执行的页码数
	 */
	public long[] getThreadPage(int threadCount) {
		if (threadCount < 1 || threadCount > MAX_THREAD_COUNT) {
			threadCount = 1;
		}
		long[] pageArray = new long[threadCount];
		for (int i = 0;i < threadCount;i++) {
			if (i == threadCount - 1) {
				pageArray[i] = pages - LongStream.of(pageArray).sum();
			} else {
				pageArray[i] = pages / threadCount;
			}
		}
		return pageArray;
	}

	/**
	 * 获取开始页码数组
	 * @param pageArray 页码数组
	 * @return 开始页码数组
	 */
	public long[] getStartPage(long[] pageArray) {
		long[] startPageArray = new long[pageArray.length];
		for (int i = 0; i < startPageArray.length; i++) {
			if (i == 0) {
				startPageArray[i] = 1;
			} else {
				int count = 0;
				for (int j = 0; j < i; j++) {
					count += pageArray[j];
				}
				startPageArray[i] = count;
			}
		}
		return startPageArray;
	}

	/**
	 * 获取当前环境中最佳的执行线程数
	 * @return 当前环境中最佳的执行线程数
	 */
	public int getThreadCount() {
		int availableProcessors = Runtime.getRuntime().availableProcessors();
		int threadCount = (int) (pages / paginationNum);
		if (threadCount < 1) {
			return 1;
		}
		if (threadCount > MAX_THREAD_COUNT) {
			threadCount = MAX_THREAD_COUNT;
		}
		if (threadCount > availableProcessors) {
			threadCount = availableProcessors;
		}
		return threadCount;
	}
}
